import { Router, RouteRecordRaw } from "vue-router";
import { RouteNameEnum, RoutePathEnum } from "@/enums/RouteEnum";
import { storage } from "@/utils/storage";
import { useAsyncRouteStoreOutSetup } from "@/store/modules/system/asyncRoute";
import { ErrorPageRoute } from "@/router/base";
import { CURRENT_USER } from "@/store/mutation-types";

/**
 * 路由拦截
 * @param router
 */
export function createRouterGuard(router: Router) {
  // 异步处理routes.
  const asyncRouteStore = useAsyncRouteStoreOutSetup();

  // 防止页面死循环重定向.
  let flag = 0;

  router.beforeEach(async (to, from, next) => {
    window.$loadingBar?.start();

    // TODO 如果需要用token, 修改这里.
    // 千万不要用cookie里的JSESSIONID做判断, 为了防止xss攻击, JSESSIONID无法通过js读取.
    const token = storage.get(CURRENT_USER);

    // 如果是在登录后跳转的是404页面, 则跳转到首页.
    if (
      from.path === RoutePathEnum.BASE_LOGIN &&
      to.name === RouteNameEnum.ERROR_PAGE
    ) {
      next(RoutePathEnum.BASE_HOME);
      return;
    }
    // 如果接下来要进入登录页面, 或进入的页面无需权限即可访问, 无需拦截.
    if (to.path === RoutePathEnum.BASE_LOGIN || to.meta.ignoreAuth) {
      next();
      return;
    }

    // 如果用户未登录.
    else if (!token && to.path) {
      // 否则重定向到登录页面.
      next({
        path: RoutePathEnum.BASE_LOGIN,
        replace: true,
      });
      window.$message?.warning("未登录或登录超时!");
      return;
    }
    let routes: RouteRecordRaw[] = [];
    try {
      routes = (await asyncRouteStore.generateRoutes()) as RouteRecordRaw[];
    } catch (e) {
      next({
        path: RoutePathEnum.BASE_LOGIN,
        replace: true,
      });
      return;
    }

    // 动态添加可访问路由表
    routes.forEach((item) => {
      router.addRoute(item as unknown as RouteRecordRaw);
    });

    const isErrorPage = router
      .getRoutes()
      .findIndex((item) => item.name === ErrorPageRoute.name);

    if (isErrorPage === -1) {
      router.addRoute(ErrorPageRoute);
    }

    // 使刷新页面能正确跳转, 而非404.
    const redirectPath = (from.query.redirect || to.path) as string;
    const redirect = decodeURIComponent(redirectPath);
    const nextData =
      to.path === redirect ? { ...to, replace: true } : { path: redirect };

    // 添加一个flag, 防止刷新后进入死循环.
    if (flag === 0 && to.matched.length === 0) {
      flag++;
      next(nextData);
    } else if (flag !== 0 && to.matched.length == 0) {
      next("/");
    } else {
      next();
    }
    window.$loadingBar?.finish();
  });

  router.afterEach((to) => {
    document.title = (to?.meta?.title as string) || document.title;
    const asyncRouteStore = useAsyncRouteStoreOutSetup();

    // 在这里设置需要缓存的组件名称
    const keepAliveComponents = asyncRouteStore.keepAliveComponents;

    const currentComName: any = to.matched.find(
      (item) => item.name == to.name
    )?.name;

    if (
      currentComName &&
      !keepAliveComponents.includes(currentComName) &&
      to.meta?.keepAlive
    ) {
      // 需要缓存的组件
      keepAliveComponents.push(currentComName);
    } else if (!to.meta?.keepAlive || to.name == "Redirect") {
      // 不需要缓存的组件
      const index = asyncRouteStore.keepAliveComponents.findIndex(
        (name) => name == currentComName
      );
      if (index != -1) {
        keepAliveComponents.splice(index, 1);
      }
    }
    asyncRouteStore.setKeepAliveComponents(keepAliveComponents);
    window.$loadingBar?.finish();
  });
}
